/**
 * MoveableObject.java
 */

package rainingcatsdogs;

import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;

/**
 * Abstract class modelling the elements of the game that will move by a set
 * amount on each iteration of the game's main loop
 */
public abstract class MovableObject extends Sprite {

	/**
	 * The number of frames of the image that is being stored for this object
	 * that correspond to the frames that are for its explosion
	 */
	private int explodeFrames;

	/**
	 * The number of frames left in the explode animation, if this hits 0 then
	 * we have finished with this object
	 */
	private int framesLeft;

	/**
	 * The amount to move in the x direction either positive or negative (will
	 * be handled by a boolean) when we call move on the object
	 */
	private int xStep;

	/**
	 * The amount to move in the y direction either positively or negatively
	 * depending on a boolean passed to the move method
	 */
	private int yStep;

	/**
	 * Constructor for the class Movable Object. It contains a call to the super
	 * class sprite which takes an image and a frame width/height. The frame
	 * width height enables us to split a single image into frames for animation
	 * to occur.
	 * 
	 * @param explodeFrames
	 *            The number of frames related to the objects explosion
	 *            animation.
	 * @param image
	 *            The image for the sprite to take.
	 * @param frameWidth
	 *            The frame width of each frame in the image.
	 * @param frameHeight
	 *            The frame Height of each frame in the image.
	 */
	public MovableObject(int explodeFrames, Image image, int frameWidth,
			int frameHeight) {
		super(image, frameWidth, frameHeight);
		this.explodeFrames = explodeFrames;
		this.framesLeft = explodeFrames;

	}

	/**
	 * Remove from the list of items of that type and then play the animation
	 * for the given number of frames that corresponds to the number of frames
	 * there are for the animation of the movable object to be destroyed.
	 * 
	 * @return returns true if we have finished with the object and can remove
	 *         it from list in canvas returns false if its still in use i.e it
	 *         still has frames left
	 */
	public boolean destroy() {

		this.setFrame(explodeFrames - framesLeft);
		framesLeft--;
		if (framesLeft == 0) {
			return true;
		}
		return false;

	}

	/**
	 * Move the current object by its x and y step values so that it can be
	 * drawn where we want it now
	 * 
	 * @param x
	 *            If true we move right, else left
	 * @param y
	 *            If true we move up else, down
	 * @param canvasHeight
	 *            The height of the canvas to be able to perform boundary
	 *            detection
	 * @param canvasWidth
	 *            The width of the canvas to be able to perform boundary
	 *            detection
	 */
	public void move(boolean x, boolean y, int canvasHeight, int canvasWidth) {
		// If we want to move right in the X direction this will be positive so
		// we add x step
		if (x) {
			// if y is also positive then we want to move up by subtracting
			// ystep from the y coords
			if (y) {
				// If we wont be moving off the right hand side of the screen or
				// above the screen
				if ((getX() + this.getWidth() + xStep) <= canvasWidth
						&& (getY() - yStep) >= 0) {
					setPosition(getX() + xStep, getY() - yStep);
				}
				// else if we will be moving off the right but not off the top
				else if ((getX() + this.getWidth() + xStep) > canvasWidth
						&& (getY() - yStep) >= 0) {
					setPosition(canvasWidth - getWidth(), getY() - yStep);
				}
				// else we are moving up off the screen but not off the right
				else if ((getX() + this.getWidth() + xStep) <= canvasWidth
						&& (getY() - yStep) < 0) {
					setPosition(getX() + xStep, 0);
				}
				// else we are moving both up off the screen and right too far
				// off the screen
				else {
					setPosition(canvasWidth - getWidth(), 0);

				}
			}
			// if not y (this means we want to move down and right)
			else {
				// If we want to keep moving right but down this time
				if ((getX() + this.getWidth() + xStep) <= canvasWidth
						&& (getY() + yStep + this.getHeight()) <= canvasHeight) {
					setPosition(getX() + xStep, getY() + yStep);
				}
				// else if we will be moving off the right but not off the
				// bottom
				else if ((getX() + this.getWidth() + xStep) > canvasWidth
						&& (getY() + yStep + this.getHeight()) <= canvasHeight) {
					setPosition(canvasWidth - this.getWidth(), getY() + yStep);
				}
				// else we are moving down off the screen but not off the right
				else if ((getX() + this.getWidth() + xStep) <= canvasWidth
						&& (this.getHeight() + yStep) > canvasHeight) {
					setPosition(getX() + xStep, canvasHeight - getHeight());
				}
				// else we are moving down off the screen and too far right off
				// the screen
				else {
					setPosition(canvasWidth - this.getWidth(), canvasHeight
							- this.getHeight());
				}
			}

		}
		// if x is false so we want to move left
		else {
			// if y is true so we want to move up
			if (y) {
				// If we wont be moving off the left hand side of the screen or
				// above the screen
				if ((getX() - xStep) >= 0 && (getY() - yStep) >= 0) {
					setPosition(getX() - xStep, getY() - yStep);
				}
				// else if we will be moving off the left but not off the top
				else if ((getX() - xStep) < 0 && (getY() - yStep) >= 0) {
					setPosition(0, getY() - yStep);
				}
				// else we are moving up off the screen but not off the left
				else if ((getX() - xStep) >= 0 && (getY() - yStep) < 0) {
					setPosition(getX() - xStep, 0);
				}
				// else we are moving both off the left and off the top of the
				// screen
				else {
					setPosition(0, 0);
				}
			}
			// if not y (this means we want to move down and left)
			else {
				// If we want to keep moving left but down this time
				if ((getX() - xStep) >= 0
						&& (getY() + yStep + this.getHeight()) <= canvasHeight) {
					setPosition(getX() - xStep, getY() + yStep);
				}
				// else if we will be moving off the left but not off the bottom
				else if ((getX() - xStep) < 0
						&& (getY() + yStep + this.getHeight()) <= canvasHeight) {
					setPosition(0, getY() + yStep);
				}
				// else we are moving down off the screen but not off theleft
				else if ((getX() - xStep) >= 0
						&& (getY() + yStep + this.getHeight()) > canvasHeight) {
					setPosition(getX() - xStep, canvasHeight - getHeight());
				}
				// else we are trying to move down off the screen and left off
				// the screen
				else {
					setPosition(0, canvasHeight - getHeight());
				}

			}
		}

	}

	/**
	 * Get the value we move in the X direction
	 * 
	 * @return The amount of x pixels to move per iteration of the game
	 */
	public int getXStep() {
		return xStep;
	}

	/**
	 * Set the xStep of the movable object
	 * 
	 * @param xStep
	 *            The number of horizontal pixels to move iteration
	 */
	public void setXStep(int xStep) {
		this.xStep = xStep;
	}

	/**
	 * Get the value we move in the Y direction
	 * 
	 * @return The amount of y pixels to move per iteration of the game
	 */
	public int getYStep() {
		return yStep;
	}

	/**
	 * Set the yStep of the movable object
	 * 
	 * @param yStep
	 *            The number of vertical pixels to move iteration
	 */
	public void setYStep(int yStep) {
		this.yStep = yStep;
	}

	/**
	 * Set the number of frames left to the specified value
	 * @param framesLeft
	 *            the framesLeft to set
	 */
	public void setFramesLeft(int framesLeft) {
		this.framesLeft = framesLeft;
	}
}
